﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.IO;

namespace Magento.Generation
{
    class PHP
    {
        private string _namespace = "";
        private List<String> _uses = new List<string>();
        private string _type = "class";
        private List<String> _extends = new List<string>();
        private List<String> _implements = new List<string>();
        private string _className = "";
        private List<List<String>> _methods = new List<List<String>>();
        private List<String> _classComments = new List<string>();

        public PHP setNamespace(string _namespace) {
            this._namespace = _namespace;
            return this;
        }

        public PHP setClassName(string className) {
            this._className = className;
            return this;
        }

        public PHP setUse(string _use) {
            this._uses.Add(_use);
            return this;
        }

        public PHP setExtends(string extends) {
            if (!extends.StartsWith(@"\"))
                this._extends.Add(@"\"+extends);
            else
                this._extends.Add(extends);
            return this;
        }

        public PHP setType(string _type) {
            this._type = _type;
            return this;
        }

        public PHP setImplements(string implements) {
            this._implements.Add(implements);
            return this;
        }

        public PHP setMethod(List<String> method) {
            this._methods.Add(method);
            return this;
        }

        public PHP setFullClassName(string fullClassName) {
            string[] classSplit = fullClassName.Replace("/", "\\").Split(new Char[1] { '\\' });
            string _namespace = String.Join("\\", classSplit.ToList().GetRange(0, classSplit.Length - 1).ToArray());
            string _className = classSplit[classSplit.Length - 1];
            this.setNamespace(_namespace);
            this.setClassName(_className);
            return this;
        }

        public PHP setClassComment(string comment) {
            this._classComments.Add(comment);
            return this;
        }

        public List<String> toList()
        {
            var content = new List<String>();

            content.Add("<?php");
            content.Add($"namespace {this._namespace};");
            content.Add("");

            // use
            if (this._uses.Count > 0) {
                foreach(var _use in this._uses) {
                    content.Add($"use {_use};");
                }
                content.Add("");
            }

            // comment
            if (this._classComments.Count > 0)
            {
                content.Add("/**");
                foreach (var comment in this._classComments)
                {
                    content.Add($" * {comment}");
                }
                content.Add(" */");
            }

            // extends and implements
            var classLine = $"{this._type} {this._className}";
            if (this._extends.Count > 0) {
                classLine += " extends "+String.Join(", ", this._extends);
            }
            if (this._implements.Count > 0)
            {
                classLine += " implements " + String.Join(", ", this._implements);
            }

            content.Add(classLine);

            // methods
            if (this._methods.Count > 0)
            {
                content.Add("{");
                foreach (var method in this._methods)
                {
                    foreach (var _method in method)
                    {
                        content.Add($"    {_method}");
                    }
                }
                content.Add("}");
            }
            else {
                content.Add("{}");
            }
            return content;
        }

        public bool toFile(string filePath) {
            if (File.Exists(filePath)) return false;
            string dir = Path.GetDirectoryName(filePath);
            if (!Directory.Exists(dir))
            {
                Directory.CreateDirectory(dir);
            }
            using (StreamWriter _file = new StreamWriter(filePath, false))
            {
                foreach (string line in this.toList())
                {
                    _file.WriteLine(line);
                }
            }
            return true;
        }
    }
}
